﻿#ifndef _JSON_H_
#define _JSON_H_

#include <iostream>
#include <fstream>
#include <string>
#include <vector>
#include <map>
#include <memory>
#include <sstream>
#include <math.h>
#include "exceptions.hpp"

namespace SimpleJson
{
    class JsonReader;
    class Json;
    class JsonParser;

#if defined(UNICODE)
    typedef std::wstring tstring;
#elif defined(U16)
    typedef std::u16string tstring;
#elif defined(U32)
    typedef std::u32string tstring;
#else
    typedef std::string tstring;
#endif

    // Json 值类型
    enum JsonValueType : unsigned char
    {
        JSON_VALUE_TYPE_INT = 0,    // 整型
        JSON_VALUE_TYPE_DOUBLE,     // 浮点型
        JSON_VALUE_TYPE_BOOL,       // 布尔型
        JSON_VALUE_TYPE_STRING,     // 字符串型
        JSON_VALUE_TYPE_ARRAY,      // 数组型
        JSON_VALUE_TYPE_OBJECT,     // 对象型
        JSON_VALUE_TYPE_NULL,       // 空
    };

    // Json 文件读取类
    class JsonReader
    {
    public:
        // 获取当前字符
        char currChar() const;

        // 获取当前字符并移动游标到下一字符,然后更新行号列号
        char getChar();

        // 从当前游标取 n 个字符,不更新游标
        std::string strAhead(int n) const;

        // 从当前游标取 n 个字符并更新游标
        std::string getStr(int n);

        // 获取当前行列号
        int getCurrLine() const;
        int getCurrCol() const;

        // 忽略空白字符
        void skip();

        // 是否读取结束
        bool isEOF() const;

    public:
        JsonReader();
        explicit JsonReader(const std::string& src_str_);
        explicit JsonReader(std::ifstream& input_file_stream_);
        ~JsonReader();

    private:
        std::string   src_str;         // 读取的 Json 文件内容
        int           src_str_len;     // Json 文件大小
        int           curr_pos;        // 当前游标
        int           curr_line;       // 当前行号,从 1 开始
        int           curr_col;        // 当前列号,从 1 开始
        bool          eof_flag;        // EOF 标志
    };

    // Json 节点类
    class Json
    {
    public:
        typedef std::map<std::string, Json> ObjValueType;
        typedef std::vector<Json>           ArrayValueType;

    private:
        // 值集合
        union Value
        {
            int                     value_int;             // int 型值
            double                  value_double = 0.0;    // double 型值,初始化最大的成员即可
            bool                    value_bool;            // bool 型值
            tstring*                value_string;          // string 型值
            ObjValueType*           value_obj;             // obj 型值
            ArrayValueType*         value_array;           // array 型值
        };

    public:
        // 获取值类型
        JsonValueType  getValueType() const;
        
        // 获取值
        int                   getIntValue() const;
        double                getDoubleValue() const;
        bool                  getBoolValue() const;
        const tstring&        getStringValue() const;
        const ObjValueType&   getObjectValue() const;
        const ArrayValueType& getArrayValue() const;

        // 设置值
        void         setValue(int value_);
        void         setValue(double value_);
        void         setValue(bool value_);
        void         setValue(const tstring& value_);
        void         setValue(const char* value_);
        void         setValue(const ObjValueType& value_);
        void         setValue(const ArrayValueType& value_);

        // 便利赋值操作符
        double         operator = (double value_);
        int            operator = (int value_);
        bool           operator = (bool value_);
        tstring        operator = (const tstring& value_);
        tstring        operator = (const char* value_);
        ObjValueType   operator = (const ObjValueType& value_);
        ArrayValueType operator = (const ArrayValueType& value_);

        // 获取子节点个数
        int getChildrenSize() const;

    public:
        // 子元素插入
        void pushBack(const Json& node, const std::string& key = "");
        void pushFront(const Json& node);
        void clear();

    public:
        // 复杂类型节点(对象或数组)元素存取
        bool      setArray(int size = 0);
        Json&     arrayGet(int index);
        void      arrayInsert(const Json& node, int index);
        void      arrayErase(int index);

        bool      objHasItem(const std::string& key);
        Json&     objGetItem(const std::string& key);
        void      objSetItem(const std::string& key, const Json& node);
            
    public:
        // 序列化当前节点的 Json 字符串
        void toJsonStr(std::string& dst_str_, 
                       bool print_key_ = true, 
                       int tab_num_ = 0, 
                       bool one_line_per_element_ = false) const;

        // 便利存取操作符
        Json& operator [] (const std::string& key);
        Json& operator [] (int array_ind_);

        // 对于简单类型可以返回不同形式的值
        int         asInt() const;
        double      asDouble() const;
        bool        asBool() const;
        std::string asString() const;

    public:
        explicit Json(JsonValueType value_type_ = JSON_VALUE_TYPE_NULL);
        Json(int value);
        Json(double value);
        Json(bool value);
        Json(const tstring& value);
        Json(const char* value);
        Json(const ObjValueType& value);
        Json(const ArrayValueType& value);

        ~Json();
        Json(const Json& node);
        Json& operator = (const Json& node);

    private:
        // 设置值类型
        void setValueType(JsonValueType value_type_);

        // 获取值类型描述字符串
        std::string getValueTypeStr(void) const;

    private:
        Value            value;           // 值集合
        JsonValueType    value_type;      // 值类型

        friend class JsonParser;
    };

    // Json 解析类
    class JsonParser
    {
    public:
        // 获取解析后的根节点
        Json& getRoot();

        // 解析成功与否
        bool succeed() const;
        bool fail() const;

    public:
        // 序列化相关(字符串或文件)
        void toString(std::string& output_str_, bool one_line_per_item_ = false) const;
        bool save(const std::string& output_file_path_, bool one_line_per_item_ = false) const;

    public:
        JsonParser();
        explicit JsonParser(const std::string& json_str_);
        explicit JsonParser(std::ifstream& ifs);
        ~JsonParser();

    private:
        // 解析相关
        void parseValue(Json& node, JsonReader& reader);
        void parseNumber(Json& node, JsonReader& reader);
        void parseString(Json& node, JsonReader& reader);
        void parseArray(Json& node, JsonReader& reader);
        void parseObject(Json& node, JsonReader& reader);

    private:
        Json    root;      // Json 根节点
        bool    success;   // 是否解析成功的标志
    };

    // unicode -> utf-8
    std::string encode_utf8(long unicode);

    tstring toTString(const std::string& str);
    std::string fromTString(const tstring& str);

} // namespace SimpleJson

#endif // _JSON_H_
